#include "spatialObjectBase.h"
#include "Fusion/spatialgrid.h"
#include "geography.h"
#include <QTime>
#include <QDebug>

SpatialObjectBase::SpatialObjectBase(quint64 objectID, double longit, double lat)
{
    this->objectID=objectID;
    this->longitude=longit;
    this->latitude=lat;
}

void SpatialObjectBase::setDistance()
{
    dist2Top=Geography::GetDistance(latitude,longitude,
                  spatialGrid->lowerLeftLatidueInDegree+GRID_SPAN,longitude);
    dist2Right=Geography::GetDistance(latitude,longitude,
                  latitude,spatialGrid->lowerLeftLongitudeInDegree+GRID_SPAN);
    dist2Bottom=Geography::GetDistance(latitude,longitude,
                  spatialGrid->lowerLeftLatidueInDegree,longitude);
    dist2Left=Geography::GetDistance(latitude,longitude,
                  latitude,spatialGrid->lowerLeftLongitudeInDegree);

    dist2TopRight=Geography::GetDistance(latitude,longitude,
                  spatialGrid->lowerLeftLatidueInDegree+GRID_SPAN,spatialGrid->lowerLeftLongitudeInDegree+GRID_SPAN);
    dist2BottomRight=Geography::GetDistance(latitude,longitude,
                  spatialGrid->lowerLeftLatidueInDegree,spatialGrid->lowerLeftLongitudeInDegree+GRID_SPAN);
    dist2BottomLeft=Geography::GetDistance(latitude,longitude,
                  spatialGrid->lowerLeftLatidueInDegree,spatialGrid->lowerLeftLongitudeInDegree);
    dist2TopLeft=Geography::GetDistance(latitude,longitude,
                  spatialGrid->lowerLeftLatidueInDegree+GRID_SPAN,spatialGrid->lowerLeftLongitudeInDegree);
}

QList <SpatialObjectBase*> SpatialObjectBase::getNeighborObjects(double eps)
{
    QList <SpatialObjectBase*> listNeighborOBJS;
    QList<SpatialObjectBase*> listCandidateObjBase=spatialGrid->getSpatialObjects();

    if(dist2Top<=eps)
        listCandidateObjBase.append(spatialGrid->northGrid->getSpatialObjects());
    if(dist2Right<=eps)
        listCandidateObjBase.append(spatialGrid->eastGrid->getSpatialObjects());
    if(dist2Bottom<=eps)
        listCandidateObjBase.append(spatialGrid->southGrid->getSpatialObjects());
    if(dist2Left<=eps)
        listCandidateObjBase.append(spatialGrid->westGrid->getSpatialObjects());

    if(dist2TopRight<=eps)
        listCandidateObjBase.append(spatialGrid->northEastGrid->getSpatialObjects());
    if(dist2BottomRight<=eps)
        listCandidateObjBase.append(spatialGrid->southEastGrid->getSpatialObjects());
    if(dist2BottomLeft<=eps)
        listCandidateObjBase.append(spatialGrid->southWestGrid->getSpatialObjects());
    if(dist2TopLeft<=eps)
        listCandidateObjBase.append(spatialGrid->northWestGrid->getSpatialObjects());

    while(!listCandidateObjBase.isEmpty())
    {
        SpatialObjectBase* currentSOBJ=listCandidateObjBase.first();
        listCandidateObjBase.removeFirst();

        if(objectID!=currentSOBJ->getObjectID())
        {
            double dis=distanceTo(currentSOBJ); //distanceTo是虚函数，会实现动态联编
            if(dis<=eps)
                listNeighborOBJS.append(currentSOBJ);
        }
    }
    return listNeighborOBJS;
}

void SpatialObjectBase::expandCluster(SpatialObjectBase* coreObj, QHash<quint64, SpatialObjectBase *> &hashIDNeighborObjs,
           QList<SpatialObjectBase *> &cluster, QHash<quint64, SpatialObjectBase *> &hashIDIteratingSPOBJ,
                                      double eps, quint32 minPts)
{
    cluster.append(coreObj); //进入了簇中的点从spatialGrid中删除
    coreObj->getSpatialGrid()->removeOneSpatialObjectBasePointer(coreObj->getObjectID());
    QTime time;
    time.start();
    while(!hashIDNeighborObjs.isEmpty())
    {
        QHashIterator <quint64,SpatialObjectBase*>  i(hashIDNeighborObjs);
        if(i.hasNext())
        {
            i.next();
            SpatialObjectBase *sOBJ=i.value();
            hashIDNeighborObjs.remove(sOBJ->getObjectID());
            time.start();
            QList <SpatialObjectBase*> listNewNeighborSPOBJ=sOBJ->getNeighborObjects(eps);
            //qDebug()<<"listNewneighbor size is:"<<listNewNeighborSPOBJ.size();
            if(listNewNeighborSPOBJ.size()>=minPts)
            {
                mergeList2Hash(listNewNeighborSPOBJ,hashIDNeighborObjs);
            }

            cluster.append(sOBJ);
            sOBJ->getSpatialGrid()->removeOneSpatialObjectBasePointer(sOBJ->getObjectID());
            hashIDIteratingSPOBJ.remove(sOBJ->getObjectID());
            //qDebug()<<"Size of listNeighborObjs:"<<hashIDNeighborObjs.size();
        }
    }
}

void SpatialObjectBase::mergeList2Hash(QList <SpatialObjectBase*> listSPOBJ,
                          QHash <quint64,SpatialObjectBase*> &hashIDSPOBJ)
{
    while (!listSPOBJ.isEmpty()) {
        hashIDSPOBJ.insert(listSPOBJ.first()->getObjectID(),listSPOBJ.first());
        listSPOBJ.removeFirst();;
    }
}
quint64 SpatialObjectBase::getObjectID() const
{
    return objectID;
}

void SpatialObjectBase::setObjectID(const qint32 &value)
{
    objectID = value;
}

double SpatialObjectBase::getLongitude() const
{
    return longitude;
}

void SpatialObjectBase::setLongitude(const double &value)
{
    longitude = value;
}


void SpatialObjectBase::setLatitude(const double &value)
{
    latitude = value;
}

SpatialGrid *SpatialObjectBase::getSpatialGrid() const
{
    return spatialGrid;
}

void SpatialObjectBase::setSpatialGrid(SpatialGrid *value)
{
    spatialGrid = value;
}

double SpatialObjectBase::getLatitude() const
{
    return latitude;
}

SpatialObjectBase::~SpatialObjectBase()
{
    
}
